﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Transactions;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using FluentValidation;
using Microsoft.Practices.Unity;
using PicStore.BLL;
using PicStore.BLL.Interface;
using PicStore.Common;
using PicStore.Common.Sorter;
using PicStore.Model;
using PicStore.Web.Filters;
using PicStore.Web.Models;
using PicStore.Web.Models.User;
using WebMatrix.WebData;

namespace PicStore.Web.Controllers
{
    [Authorize]
    public class UserController : BaseController
    {
        public const int PageSize = 10;

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult GetUsers(string name, string orderBy, int pageIndex = 1, bool isAsc = true)
        {
            string keyTosearch = string.Empty;
            if (string.IsNullOrEmpty(name) == false)
            {
                keyTosearch = name;
            }
            List<User> allUsers = UserService.GetAllUsers(keyTosearch);
            List<UserModel> list = (from u in allUsers
                                    select UserModel.BuildUserModel(u)).ToList();
            IList<UserModel> sortedList = new SortList<UserModel, string>(list, orderBy, isAsc);

            int count = sortedList.Count();
            int totalPages = count / PageSize + (count % PageSize > 0 ? 1 : 0);

            IEnumerable<UserModel> result = sortedList.Skip((pageIndex - 1) * PageSize).Take(PageSize);
            return Json(new { Data = result.ToArray(), TotalPages = totalPages }, JsonRequestBehavior.AllowGet);
        }

        private List<SelectListItem> GetRoleList()
        {
            var roles = UserService.GetRoles();
            List<SelectListItem> list = new List<SelectListItem>();
            foreach (var r in roles)
            {
                SelectListItem item = new SelectListItem
                {
                    Text = r.Name,
                    Value = r.Id.ToString(),
                };
                if (item.Text.ToLower() == RoleEnum.Viewer.ToString().ToLower())
                {
                    item.Selected = true;
                }
                list.Add(item);
            }
            return list;
        }

        public ActionResult Add()
        {
            ViewBag.Action = "Add";
            ViewBag.OnSuccess = "viewModel.onDataAdded";
            var model = new UserModel();
            model.RoleList = GetRoleList();
            return View("Add", model);
        }

        [HttpPost]
        public ActionResult Add(UserModel model)
        {
            string errorPrefix = "Add user failed: ";
            try
            {
                if (ModelState.IsValid)
                {
                    var validator = new UserModelValidator();
                    validator.ValidateAndThrow(model);

                    UserService.CreateUser(model.UserName, model.Password, model.Email, model.Department, model.Phone, model.Mobile, model.RoleId);

                    var createdUser = UserService.GetUser(model.UserName);
                    model = UserModel.BuildUserModel(createdUser);
                    model.IsValid = true;
                }
                else
                {
                    model.IsValid = false;
                    model.ErrorMessage = errorPrefix + "model state is invalid.";
                }
            }
            catch (ValidationException validateionExp)
            {
                StringBuilder builder = new StringBuilder();
                foreach (var failure in validateionExp.Errors)
                {
                    this.ModelState.AddModelError(failure.PropertyName, failure.ErrorMessage);
                    builder.AppendFormat("Field {0} has error: {1}", failure.PropertyName, failure.ErrorMessage);
                }
                model.IsValid = false;
                model.ErrorMessage = errorPrefix + builder.ToString();
            }
            catch (ArgumentException argExp)
            {
                model.IsValid = false;
                model.ErrorMessage = errorPrefix + argExp.Message;
            }
            catch (Exception e)
            {
                Log.Severe(e.ToString());

                model.IsValid = false;
                model.ErrorMessage = errorPrefix + Constants.SevereError + e.Message;
            }

            return Json(model);
        }

        public ActionResult Update(string id)
        {
            ViewBag.Action = "Update";
            ViewBag.OnSuccess = "viewModel.onDataUpdated";
            var user = UserService.GetUser(int.Parse(id));
            var model = EditUserModel.BuildUserModel(user);
            model.RoleList = GetRoleList();
            return View("Edit", model);
        }

        [HttpPost]
        public ActionResult Update(EditUserModel contact)
        {
            UserService.UpdateUser(contact.Id, contact.Email, contact.Department, contact.Phone, contact.Mobile, contact.RoleId);
            var user = UserService.GetUser(contact.Id);
            return Json(UserModel.BuildUserModel(user));
        }

        public ActionResult ResetPassword(string id)
        {
            ViewBag.Action = "ResetPassword";
            ViewBag.OnSuccess = "viewModel.onDataReseted";
            var user = UserService.GetUser(int.Parse(id));
            var model = ResetPasswordModel.BuildUserModel(user);
            return View("ResetPassword", model);
        }

        [HttpPost]
        public ActionResult ResetPassword(ResetPasswordModel model)
        {
            string errorPrefix = "Reset password failed: ";
            try
            {
                if (ModelState.IsValid)
                {
                    var validator = new ResetPasswordModelValidator();
                    validator.ValidateAndThrow(model);

                    UserService.ResetPassword(model.Id, model.Password);
                    model.IsValid = true;
                    model.ErrorMessage = "Reset password success";
                }
                else
                {
                    model.IsValid = false;
                    model.ErrorMessage = errorPrefix + "model state is invalid.";
                }
            }
            catch (ValidationException validateionExp)
            {
                StringBuilder builder = new StringBuilder();
                foreach (var failure in validateionExp.Errors)
                {
                    this.ModelState.AddModelError(failure.PropertyName, failure.ErrorMessage);
                    builder.AppendFormat("Field {0} has error: {1}", failure.PropertyName, failure.ErrorMessage);
                }
                model.IsValid = false;
                model.ErrorMessage = errorPrefix + builder.ToString();
            }
            catch (Exception e)
            {
                Log.Severe(e.ToString());

                model.IsValid = false;
                model.ErrorMessage = errorPrefix + Constants.SevereError + e.Message;
            }

            return Json(model);
        }

        public ActionResult Delete(string id)
        {
            var user = UserService.GetUser(int.Parse(id));
            UserService.ShieldUser(user.UserId);
            return Json(UserModel.BuildUserModel(user), JsonRequestBehavior.AllowGet);
        }
    }
}
